﻿using System.Windows;
using GameEngine.Clients.Silverlight;
using GameEngine.Model.Data;
using GameEngine.Model;
using GameEngine.Model.Data.implementation;
using PureMVC.Patterns;
using PureMVC.Interfaces;
using GameEngine.Clients.Silverlight.View.Components;
using GameEngine.Clients.Silverlight.View;
using System.Collections.Generic;
using MapEngine;
using System;
using SilverlightResources;
using SLPerlinNoise;
using System.Windows.Media;

namespace MyUniverse
{
    public class MyFacade : SampleSilverlightFacade
    {
        public static ViewStateVO deadState = new ViewStateVO("dead");

        protected override void InitializeController()
        {
            base.InitializeController();

            RegisterCommand(FPS_NOTIFICATION, typeof(FPSCommand));//TODO meter isto como evento
        }

        override protected void CreateModelFacade()
        {
            new MyModel();
        }

        //private const string STARTUP_COMMAND = "StartupCommand";

        // Override Singleton Factory method 
        public new static MyFacade Instance
        {
            get
            {
                return SampleSilverlightFacade.Instance as MyFacade;
            }
        }

        public void LoadGame(IGameVO<int> game)
        {
            if (game == null)
            {
                game = CreateGame();
            }
            IGameDataProxy<int> gameDP = SilverlightApplicationFacadeHelper.CreateGame(game);
            SilverlightApplicationFacadeHelper.StartLevel(game.LevelOrder[game.CurrentLevel]);

            //GameMenuUC gameScreen = new GameMenuUC(gameDP);
            SilverlightApplicationFacadeHelper.DesktopNavigate(SampleSilverlightViewFacade.Helper.GetGameView() as FrameworkElement);
        }

        public IGameVO<int> CreateGame()
        {
            //TODO meter isto em config file

            IGameVO<int> game = new GameVO<int>(new GameVOId("1")) { 
                Name = "New game",
                MinHeight = 0,
                MaxHeight = 50,
            };
            ILevelVO<int> level = new LevelVO<int>(new LevelVOId("lvl1"))
            {
                Name = "myUni"
            };
            MapVO<int> map = new MapVO<int>("uniMap");
            map.CreateTiles(new Point(15, 15));
            //PerlinNoise3D.GenerateHeightsFromPerlin(map, new Point(15, 5), 0.03f, 1, 1, 1, 1,game.MinHeight, game.MaxHeight);
            PerlinNoise3D.GenerateHeightsFromPerlin(map.Tiles, new Point(30, 20), 0.025f, 1, 0.5f, 2, 1, game.MinHeight, game.MaxHeight);
            //map.Tiles[5][5].Height = 10;
            map.Camera.Position = new Point(7, 7);
            map.Camera.Scale = 3f;
            WorldVO<int> world = new WorldVO<int>(new WorldVOId("MyWorld"))
            {
                Map = map,
            };
            level.Worlds.Add(world);
            game.Levels.Add(level);
            game.CurrentLevel = 0;
            game.LevelOrder.Add(0, level.Id);

            //Add Views
            #region Views
            var blackSphere = new ShapeVO(new ShapeVOId(MyShapes.NewShapeID), new ShapeTypeVOId(ItemUC.ShapeTypeElipse))
            {
                Position = new MapEngine.Point3d(),
                TypeModifiers = ItemUC.createEllipseModifiers(new Point3d(new Point(0, 0), 5), new Point(10,10), Colors.Black)
            };
            var malePeasantView = SpriteMaleAndFemale.createMaleView(MyModel.Instance.CreateNewId(), "male");
            malePeasantView.AddShape(blackSphere, deadState);

            var femalePeasantView = SpriteMaleAndFemale.createFemaleView(MyModel.Instance.CreateNewId(), "female");
            femalePeasantView.AddShape(blackSphere, deadState);

            IViewVO<int> arvoreView = MyShapes.createTree(MyModel.Instance.CreateNewId(), "tree", new Point3d(new Point(5, 5), 10), new Point(20, 20));
            IViewVO<int> ervaView = MyShapes.createGrass(MyModel.Instance.CreateNewId(), "grass", new Point(5, 5));

            game.Views.Add(malePeasantView);
            game.Views.Add(femalePeasantView);
            //game.Views.Add(predadorView.Id, predadorView);
           // game.Views.Add(presaView.Id, presaView);
            game.Views.Add(ervaView);
            game.Views.Add(arvoreView);
            #endregion

            #region Types
            //Add ThingTypes
            AnimalTypeVO humanMaleType = new AnimalTypeVO(new ThingTypeVOId(MyModel.Instance.CreateNewId()) { Name = "humanMale" })
            {
                Velocity = 0.15f,
                ViewId = malePeasantView.Id
            };
            game.ThingTypes.Add(humanMaleType);

            AnimalTypeVO humanFemaleType = new AnimalTypeVO(new ThingTypeVOId(MyModel.Instance.CreateNewId()) { Name = "humanFemale" })
            {
                Velocity = 0.15f,
                ViewId = femalePeasantView.Id
            };
            game.ThingTypes.Add(humanFemaleType);


            //ThinkingThingTypeVO<int> predadorType = new ThinkingThingTypeVO<int>(new ThingTypeVOId<int>(MyModel.Instance.CreateNewId(), "predador"))
            //{
            //    Velocity = 0.15f,
            //    ViewId = predadorView.Id
            //};
            //game.ThingTypes.Add(predadorType.Id, predadorType);

            VegetalTypeVO ervaType = new VegetalTypeVO(new ThingTypeVOId(MyModel.Instance.CreateNewId()) { Name = "vegetal" })
            {
                ViewId = ervaView.Id
            };
            game.ThingTypes.Add(ervaType);

            ThingTypeVO<int> arvoreType = new ThingTypeVO<int>(new ThingTypeVOId(MyModel.Instance.CreateNewId()) { Name = "arvore" })
            {
                ViewId = arvoreView.Id
            };
            game.ThingTypes.Add(arvoreType);
            #endregion

            #region Items
            ///     Items

            //predadores
            //world.Items.Add(new ThinkingThingVO<int>(new ThingVOId<int>(SilverlightModelFacade.Instance.CreateNewId()), predadorType.Id) { 
            //    Position = new MapEngine.Point3d(new Point(12,12),0),
            //    //Brain      
            //});
            //world.Items.Add(new ThinkingThingVO<int>(new ThingVOId<int>(SilverlightModelFacade.Instance.CreateNewId()), predadorType.Id)
            //{
            //    Position = new MapEngine.Point3d(new Point(9, 9), 0),
            //    //Brain
            //});

            //presas
            world.Items.Add(new AnimalVO(new ThingVOId<int>(SilverlightModelFacade.Instance.CreateNewId()) { Name = "MAle" }, humanMaleType.Id)
            {
                Position = new MapEngine.Point3d(new Point(9, 9), 0),
                Direction = new Point(0, -1),//south
                Energy = 50,
                Food = typeof(VegetalVO).GUID
            });
            world.Items.Add(new AnimalVO(new ThingVOId<int>(SilverlightModelFacade.Instance.CreateNewId()) { Name = "Female" }, humanFemaleType.Id)
            {
                Position = new MapEngine.Point3d(new Point(0, 0), 0),
                Direction = new Point(0, -1),//south
                Energy = 50,
                Food = typeof(VegetalVO).GUID
            });
            //world.Items.Add(presa1);
            //world.Items.Add(new AnimalVO(new ThingVOId<int>(SilverlightModelFacade.Instance.CreateNewId()), presaType.Id)
            //{
            //    Position = new MapEngine.Point3d(new Point(2, 8), 0),
            //    Direction = new Point(0, -1),//south
            //    Energy = 12,
            //    Food = typeof(VegetalVO).GUID
            //    //Brain

            //});
            //world.Items.Add(new AnimalVO(new ThingVOId<int>(SilverlightModelFacade.Instance.CreateNewId()), presaType.Id)
            //{
            //    Position = new MapEngine.Point3d(new Point(8, 2), 0),
            //    Direction = new Point(0, -1),//south
            //    Energy = 12,
            //    Food = typeof(VegetalVO).GUID
            //    //Brain
            //});

            //erva
            VegetalVO erva1 = new VegetalVO(new ThingVOId<int>(SilverlightModelFacade.Instance.CreateNewId()) { Name = "Grass" }, ervaType.Id)
            {
                Position = new MapEngine.Point3d(new Point(0, 5), 0),
                Energy = 10
            };
            world.Items.Add(erva1);
            world.Items.Add(new VegetalVO(new ThingVOId<int>(SilverlightModelFacade.Instance.CreateNewId()) { Name = "Grass" }, ervaType.Id)
            {
                Position = new MapEngine.Point3d(new Point(2, 7), 0),
                Energy = 10
            });
            world.Items.Add(new VegetalVO(new ThingVOId<int>(SilverlightModelFacade.Instance.CreateNewId()) { Name = "Grass" }, ervaType.Id)
            {
                Position = new MapEngine.Point3d(new Point(3, 1), 0),
                Energy = 10
            });
            world.Items.Add(new VegetalVO(new ThingVOId<int>(SilverlightModelFacade.Instance.CreateNewId()) { Name = "Grass" }, ervaType.Id)
            {
                Position = new MapEngine.Point3d(new Point(5, 9), 0),
                Energy = 10
            });
            world.Items.Add(new VegetalVO(new ThingVOId<int>(SilverlightModelFacade.Instance.CreateNewId()) { Name = "Grass" }, ervaType.Id)
            {
                Position = new MapEngine.Point3d(new Point(12, 2), 0),
                Energy = 10
            });
            world.Items.Add(new VegetalVO(new ThingVOId<int>(SilverlightModelFacade.Instance.CreateNewId()) { Name = "Grass" }, ervaType.Id)
            {
                Position = new MapEngine.Point3d(new Point(12, 13), 0),
                Energy = 10
            });
            world.Items.Add(new VegetalVO(new ThingVOId<int>(SilverlightModelFacade.Instance.CreateNewId()) { Name = "Grass" }, ervaType.Id)
            {
                Position = new MapEngine.Point3d(new Point(3, 8), 0),
                Energy = 10
            });
            world.Items.Add(new VegetalVO(new ThingVOId<int>(SilverlightModelFacade.Instance.CreateNewId()) { Name = "Grass" }, ervaType.Id)
            {
                Position = new MapEngine.Point3d(new Point(4, 5), 0),
                Energy = 10
            });
            world.Items.Add(new VegetalVO(new ThingVOId<int>(SilverlightModelFacade.Instance.CreateNewId()) { Name = "Grass" }, ervaType.Id)
            {
                Position = new MapEngine.Point3d(new Point(5, 5), 0),
                Energy = 10
            });

            //arvore
            world.Items.Add(new ThingVO<int>(new ThingVOId<int>(SilverlightModelFacade.Instance.CreateNewId()) { Name = "Tree" }, arvoreType.Id)
            {
                Position = new MapEngine.Point3d(new Point(0, 7), 0),
            });
            world.Items.Add(new ThingVO<int>(new ThingVOId<int>(SilverlightModelFacade.Instance.CreateNewId()) { Name = "Tree" }, arvoreType.Id)
            {
                Position = new MapEngine.Point3d(new Point(7, 0), 0),
            });
            #endregion

            return game;
        }
    }

    public class FPSCommand : SimpleCommand
    {
        override public void Execute(INotification notification)
        {

            //if (GameUC.Instance != null) {
            //    GameUC.Instance.setFPS((int)notification.Body);
            //}
        }
    }

    public class MyModel : SilverlightModelFacade
    {
        public override GameEngine.Model.IThingDataProxy<int> CreateThingDataProxy(IThingVO<int> vo)
        {
            if (vo.GetType().GUID == typeof(VegetalVO).GUID)
            {
                return new VegetalDataProxy(vo as VegetalVO);
            }
            else if (vo.GetType().GUID == typeof(AnimalVO).GUID)
            {
                return new AnimalDataProxy(vo as AnimalVO);
            }
            return base.CreateThingDataProxy(vo);
        }

        public override IThingTypeDataProxy<int> CreateThingTypeDataProxy(IThingTypeVO<int> vo)
        {
            if (vo.GetType().GUID == typeof(VegetalTypeVO).GUID)
            {
                return new ThinkingThingTypeDataProxy<int>(
                        vo as VegetalTypeVO,
                        CreateViewDataProxy(Game.Views[vo.ViewId]));
            }
            else if (vo.GetType().GUID == typeof(AnimalTypeVO).GUID)
            {
                return new AnimalTypeDataProxy(
                        vo as AnimalTypeVO,
                        CreateViewDataProxy(Game.Views[vo.ViewId]));
            }
            return base.CreateThingTypeDataProxy(vo);
        }

        public override void InitializeWorldActions()
        {
            base.InitializeWorldActions();

            //TODO adcionar método para fazer add de action sem termos que conehcer o enginedataproxy
            EngineDataProxy<int>.Instance.AddWorldAction(
                   new EngineDataProxy<int>.WorldAction(
                       typeof(AnimalDataProxy),
                       AnimalTypeDataProxyActions.Action,
                       1500
                       ));
        }
    }

}
